#pragma once

#include "Reactor.hpp"
#include <condition_variable>

// 把一个线程与一个Reactor对象关联起来
// ReactorThread是从属Reactor线程
class ReactorThread
{
private:
    // 锁和条件变量用于同步
    // 因为外界想要获取Reactor对象时，Reactor对象必须已经初始化好了
    mutex _mutex;
    condition_variable _cond;
    // Reactor的指针，这个指针指向的对象的创建和初始化必须要在线程内部进行
    Reactor *_reactor;
    // Reactor对象关联的线程
    thread _thread;

private:
    void ThreadEntry()
    {
        // 保证reactor与线程的生命周期绑定，所以创建在栈区
        Reactor reactor;
        {
            lock_guard<mutex> m(_mutex);
            // 初始化
            _reactor = &reactor;
            // 唤醒条件变量下等待的线程
            _cond.notify_all();
        }
        // 开始事件监控，处理事件
        reactor.Start();
    }

public:
    ReactorThread()
        : _reactor(nullptr),
          _thread(&ReactorThread::ThreadEntry, this)
    {
        // 线程分离
        _thread.detach();
    }
    Reactor *GetReactor()
    {
        // 加锁保护_reactor
        unique_lock<mutex> mutex(_mutex);
        while (_reactor == nullptr)
        {
            // 阻塞等待
            _cond.wait(mutex);
        }
        return _reactor;
    }
};